/**
 * @file	Infrasound.Time.h
 * @ingroup	libTime
 * @brief	Time includes GPS synchronization and all Timer functionalities
 * 
 * @author	andi
 * @since		1.1
 * @version	$Rev$
 * 
 */

#ifndef INFRASOUND_TIME_H
#define INFRASOUND_TIME_H

#include <ScatterWeb.System.h>

///< 24h in seconds
#define MIDNIGHT_SECS 86400

/**
 * local time
 * @param secs  local seconds
 * @param ticks current ticks of ACLK 1tick = 1/32768 s
 */
typedef struct{
	uint32_t secs;
	uint16_t ticks;
}rtc_time_t;

/**
 * Timer callback function pointer type.
 *
 * @since         1.0
 */
typedef void(*fp_timer)(void*); 

/**
 * @brief initializes time component. GPS synch is initiated
 *
 * @return 0 if success
 */
uint8_t time_init();

/**
 * @brief computes the time duration 
 *
 * @param from < to (otherwise 'to' is assumed to be next day)
 * @return duration in (average) ACLK ticks
 */
uint32_t time_duration(const rtc_time_t* from, const rtc_time_t* to);

/**
 * @brief adds ACLK ticks to a time value in respect to exact ACLK frequency
 *        result is checked for exceeding midnight
 *
 * @param time operand and destination of the sum
 * @ticks ACLK ticks added to time
 */
void time_addTicks(rtc_time_t* time, uint32_t ticks);

/**
* @brief adds a timer for single execution
*
* @param secs seconds
* @param ticks 1tick accords 1/32768 second
* @param fp callback executed, when delay expired
* @param data argument for the callback function
* @return 0 if success
*/
bool time_addTimer(uint16_t secs, uint32_t ticks, fp_timer fp, void* data); 
//bool time_addTimer(uint32_t ticks, fp_timer fp, void* data); 

/**
 * Removes timer if data is matching
 *
 * @param fp        function to call if expired
 * @param data      parameter to call function
 * @return          <code>True</code> if successful;
 *                  <code>False</code> otherwise. 
 * @since           1.0
 */
bool time_removeTimer(fp_timer fp, void* data);

/**
 * Decreases timer if data is matching
 *
 * @param fp        function to call if expired
 * @param data      parameter to call function
 * @param ticks     ticks of which the according timer will be decreased
 * @return          <code>True</code> if successful;
 *                  <code>False</code> otherwise. 
 * @since           1.0
 */
bool time_decreaseTimer(fp_timer fp, void* data, uint16_t ticks);

/**
 * run software timer
 * called by superloop
 */
bool time_eventHandler();



/**
 * struct of system time
 * <ul>
 * <li>secs
 * <li>millis
 * </ul>
 *  
 * @since         1.0
 */
typedef struct {
  uint32_t secs;
  uint16_t millis;
} time_t;


/**
 * returns local time
 * @para time varible to be filled with time values
 */
rtc_time_t* time_getTime(rtc_time_t* time);



/**
 * stopwatch and time measurement functionality
 */
#ifndef INFRASOUND_TIME_C
extern volatile uint32_t		time_secs;					///< local time in seconds
extern volatile uint32_t		clock1_secs;				///< software stopwatch seconds
extern volatile uint32_t		clock2_secs;				///< software stopwatch seconds
#endif

#define TIME_NOW		(rtc_time_t){time_secs, TBR}
#define TIME_ADC12		(rtc_time_t){time_secs, 0}	///< time of first sample of las ADC12 sequence
#define TIME_SOFTWARE1	(rtc_time_t){clock1_secs, TBCCR3}	///< software clock 1
#define TIME_SOFTWARE2	(rtc_time_t){clock2_secs, TBCCR4}	///< software clock 2

///< stops time of software clock (software capture)
#define STOP_SOFTWARE1	do{ \
							TBCCTL3 ^= CCIS0; \
							clock1_secs = time_secs; \
					}while(false)	
///< stops time of software clock (software capture)
#define STOP_SOFTWARE2	do{ \
							TBCCTL4 ^= CCIS0; \
							clock2_secs = time_secs; \
					}while(false)	


#endif

